package com.gzhryc.shared_device.oem.h5.agent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.gzhryc.common.IDTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.common.redis.RedisTools;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayConfig;
import com.gzhryc.shared_device.common.payment.dao.enums.WXPayConfigEnum;
import com.gzhryc.shared_device.common.payment.dao.models.WXTokenHttpConfig;
import com.gzhryc.shared_device.common.payment.services.WXPayConfigService;
import com.gzhryc.shared_device.oem.code.RedisDBConstants;
import com.gzhryc.shared_device.oem.code.agent.dao.db.Agent;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentBusinessConfig;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentRelation;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentRelationBusinessConfig;
import com.gzhryc.shared_device.oem.code.agent.services.AgentBusinessConfigService;
import com.gzhryc.shared_device.oem.code.agent.services.AgentReferrerBusinessConfigService;
import com.gzhryc.shared_device.oem.code.agent.services.AgentRelationBusinessConfigService;
import com.gzhryc.shared_device.oem.code.agent.services.AgentRelationService;
import com.gzhryc.shared_device.oem.code.agent.services.AgentService;
import com.gzhryc.shared_device.oem.code.agent.services.dto.AgentReferrerBusinessConfigSearch;
import com.gzhryc.shared_device.oem.code.config.PowerEnum;
import com.gzhryc.shared_device.oem.code.place.dao.db.Clerk;
import com.gzhryc.shared_device.oem.code.place.services.ClerkService;
import com.gzhryc.shared_device.oem.code.user.ERoleType;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.code.user.services.UserService;
import com.gzhryc.shared_device.oem.h5.agent.dto.BusinessConfigItem;
import com.gzhryc.shared_device.oem.h5.agent.dto.VerifyCodeData;
import com.gzhryc.shared_device.oem.h5.agent.outside.GZHHttpAPIService;
import com.gzhryc.shared_device.oem.h5.agent.outside.GetGZHTokenResponse;
import com.gzhryc.weixin.gzh.WeiXinGZHAPIServer;
import com.gzhryc.weixin.gzh.WxAuthorityApi;
import com.gzhryc.weixin.gzh.WxJSSDKApi;
import com.gzhryc.weixin.gzh.WxUserApi;
import com.gzhryc.weixin.gzh.models.AccessToken;

/**
 * 会员API回话管理
 */
public class LoginUserSessionManager {

    static Logger log = Logger.getLogger(LoginUserSessionManager.class);

    static LoginUserSessionManager me;

    public static LoginUserSessionManager self() {
        if (me == null) {
            me = new LoginUserSessionManager();
        }
        return me;
    }

    private Long times = 600L;

    private ConcurrentHashMap<String, WeiXinGZHAPIServer> Store = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String, GZHHttpAPIService> httpAPIServices = new ConcurrentHashMap<>();

    public void initialWXGZHAPIServer() {
        List<WXPayConfig> wxPayConfigList = WXPayConfigService.self().findByAppType(WXPayConfigEnum.AppType.wxgzh.index());
        if (wxPayConfigList != null && wxPayConfigList.size() > 0) {
            for (WXPayConfig config : wxPayConfigList) {
                if(WXPayConfigEnum.TokenType.HttpGet.index().equals(config.getTokenType()) && StringTools.isNotBlank(config.getTokenConfigJson())){
                    WXTokenHttpConfig httpConfig = JsonTools.fromJson(config.getTokenConfigJson(),WXTokenHttpConfig.class);
                    httpAPIServices.put(config.getAppId(),new GZHHttpAPIService(httpConfig));
                }else {
                    WeiXinGZHAPIServer weiXinGZHAPIServer = new WeiXinGZHAPIServer(config.getAppId(), config.getAppSecret());
                    weiXinGZHAPIServer.run();
                    Store.put(config.getAppId(), weiXinGZHAPIServer);
                }
            }
        }
    }

    public boolean setUserSession(LoginUser loginUser) {
        try {
            String json = JsonTools.toJson(loginUser);
            if (RedisTools.get().set(RedisDBConstants.API_SESSION_DB, loginUser.getLoginToken(), json, times)) {
                //修改当前登陆类型
                String lastLoginType = loginUser.getRoleType().toString();
                if (loginUser.getParentId() != null) {
                    lastLoginType = lastLoginType + "," + loginUser.getParentId();
                }
                UserService.self().updateLastLoginType(loginUser.getId(), lastLoginType);
                if(ERoleType.Agent.index().equals(loginUser.getRoleType())) {
                	AgentService.self().replaceLastLogin(loginUser.getId());
                }else if(ERoleType.Merchant.index().equals(loginUser.getRoleType()) 
                		|| ERoleType.Partner.index().equals(loginUser.getRoleType())) {
                	AgentRelationService.self().replaceLastLogin(loginUser.getParentId(),loginUser.getId());
                }else if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
                	ClerkService.self().replaceLastLogin(loginUser.getId(), loginUser.getParentId());
                }
                return true;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        log.error("缓存登陆信息失败，登陆信息：{{0:json}}", loginUser);
        return false;
    }

    public LoginUser getUserSession(String loginToken) {
        try {
            String json = RedisTools.get().get(RedisDBConstants.API_SESSION_DB, loginToken);
            if (StringTools.isNotBlank(json)) {
                RedisTools.get().set(RedisDBConstants.API_SESSION_DB, loginToken, json, times);
                return JsonTools.fromJson(json, LoginUser.class);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public OperateInfo getOperateInfo(LoginUser loginUser,Integer roleType){
        OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE,WebConstants.PROGRAM_TYPE_NAME);
        if(roleType != null) {
            if (ERoleType.Merchant.index().equals(roleType)) {
                operateInfo.setOperator(EOperatorType.Merchant.index(), loginUser.getNickname());
            } else if (ERoleType.Partner.index().equals(roleType)) {
                operateInfo.setOperator(EOperatorType.Staff.index(), loginUser.getNickname());
            } else if (ERoleType.Clerk.index().equals(roleType)) {
                operateInfo.setOperator(EOperatorType.Clerk.index(), loginUser.getNickname());
            }
        }else {
            operateInfo.setOperator(loginUser.getRoleType(), loginUser.getNickname());
        }
        return operateInfo;
    }

    public boolean setVerifyCodeSession(VerifyCodeData verifyCodeData) {
        try {
            String json = JsonTools.toJson(verifyCodeData);
            return RedisTools.get().set(RedisDBConstants.API_SESSION_DB, verifyCodeData.getToken(), json, times);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }

    public VerifyCodeData getVerifyCode(String token) {
        try {
            String json = RedisTools.get().get(RedisDBConstants.API_SESSION_DB, token);
            if (StringTools.isNotBlank(json)) {
                return JsonTools.fromJson(json, VerifyCodeData.class);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public void removeVerifyCode(String token) {
        try {
            RedisTools.get().delete(RedisDBConstants.API_SESSION_DB, token);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    public WxAuthorityApi getWXAuthorityAPI(String appId) {
        WeiXinGZHAPIServer weiXinGZHAPIServer = Store.get(appId);
        if (weiXinGZHAPIServer != null) {
            return weiXinGZHAPIServer.getAuthorityApi();
        }else{
            GZHHttpAPIService httpAPIService = httpAPIServices.get(appId);
            if(httpAPIService != null){
                GetGZHTokenResponse tokenResponse = httpAPIService.getAccessToken(appId);
                if(tokenResponse != null){
                    AccessToken accessToken = new AccessToken();
                    accessToken.setAppid(appId);
                    accessToken.setAccess_token(tokenResponse.getBody().getAccessToken());
                    accessToken.setExpires_in(tokenResponse.getBody().getExpiresIn());
                    accessToken.setLastSetDate(tokenResponse.getBody().getLastSetDate());
                    WxAuthorityApi authorityApi = new WxAuthorityApi(accessToken);
                    return authorityApi;
                }
            }
        }
        return null;
    }

    public WxUserApi getWXUserAPI(String appId) {
        WeiXinGZHAPIServer weiXinGZHAPIServer = Store.get(appId);
        if (weiXinGZHAPIServer != null) {
            return weiXinGZHAPIServer.getUserApi();
        }else{
            GZHHttpAPIService httpAPIService = httpAPIServices.get(appId);
            if(httpAPIService != null){
                GetGZHTokenResponse tokenResponse = httpAPIService.getAccessToken(appId);
                if(tokenResponse != null){
                    AccessToken accessToken = new AccessToken();
                    accessToken.setAppid(appId);
                    accessToken.setAccess_token(tokenResponse.getBody().getAccessToken());
                    accessToken.setExpires_in(tokenResponse.getBody().getExpiresIn());
                    accessToken.setLastSetDate(tokenResponse.getBody().getLastSetDate());
                    WxUserApi userApi = new WxUserApi(accessToken);
                    return userApi;
                }
            }
        }
        return null;
    }

    public WxJSSDKApi getWxJSSDKApi(String appId) {
    	if(StringTools.isNotBlank(appId)) {
	        WeiXinGZHAPIServer weiXinGZHAPIServer = Store.get(appId);
	        if (weiXinGZHAPIServer != null) {
	            return weiXinGZHAPIServer.getJSSDKApi();
	        }else{
	            GZHHttpAPIService httpAPIService = httpAPIServices.get(appId);
	            if(httpAPIService != null){
	                GetGZHTokenResponse tokenResponse = httpAPIService.getAccessToken(appId);
	                if(tokenResponse != null){
	                    AccessToken accessToken = new AccessToken();
	                    accessToken.setAppid(appId);
	                    accessToken.setAccess_token(tokenResponse.getBody().getAccessToken());
	                    accessToken.setExpires_in(tokenResponse.getBody().getExpiresIn());
	                    accessToken.setLastSetDate(tokenResponse.getBody().getLastSetDate());
	                    WxJSSDKApi userApi = new WxJSSDKApi(accessToken);
	                    return userApi;
	                }
	            }
	        }
    	}
        return null;
    }

    /**
     * 
     * @param user	
     * @param role	1:代理，2:商户，3:合伙人，4:介绍人，5:店员，默认是自动登陆最后一个
     * @return
     * @throws LogicException
     */
    public LoginUser loginCheck(User user, List<Integer> roleList) throws LogicException {
        String token = IDTools.getUUID();

        LoginUser loginUser = new LoginUser();
        loginUser.setId(user.getId());
        loginUser.setNickname(user.getNickname());
        loginUser.setName(user.getName());
        loginUser.setPhone(user.getPhone());
        loginUser.setLoginToken(token);

        boolean flag = false;
        if(roleList != null && roleList.size() > 0) {
        	log.info("登录角色列表：{{0:json}}", roleList);
        	for(Integer role : roleList) {
		        if(role == 1) {
		        	//代理
		        	Agent agent = AgentService.self().getByUserId(user.getId());
		            if(agent != null){
		                loginUser.setRoleType(ERoleType.Agent.index());
		                loginUser.setLevel(agent.getLevel());
		                loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Open.index()); //默认开启
		                List<AgentBusinessConfig> agentbusiConfigList = AgentBusinessConfigService.self().findByUserId(agent.getUserId());
	                	if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
	                		loginUser.setBusinessTypes(new ArrayList<>());
	                		for(AgentBusinessConfig busiConfig : agentbusiConfigList) {
	                			BusinessConfigItem item = new BusinessConfigItem();
	                			item.setBusinessType(busiConfig.getBusinessType());
	                			item.setEditFeeState(2);	//默认开启
	                			loginUser.getBusinessTypes().add(item);
	                		}
	                	}
		                flag = true;
		            }
		        }else if(role == 2) {
		        	//商户
		        	AgentRelation agentRelation = AgentRelationService.self().getLastLogin(user.getId(),ERoleType.Merchant.index());
		        	if (agentRelation != null) {
	                    loginUser.setRoleType(ERoleType.Merchant.index());
	                    loginUser.setParentId(agentRelation.getUserId());
	                    loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
	                    flag = true;
	                }
		        }else if(role == 3) {
		        	//合伙人
		        	AgentRelation agentRelation = AgentRelationService.self().getLastLogin(user.getId(),ERoleType.Partner.index());
	                if (agentRelation != null) {
	                    loginUser.setRoleType(ERoleType.Partner.index());
	                    loginUser.setParentId(agentRelation.getUserId());
	                    loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
	                    List<AgentRelationBusinessConfig> agentbusiConfigList = AgentRelationBusinessConfigService.self()
	                    		.findByUserKeys(agentRelation.getUserId(),agentRelation.getRelationUserId());
	                	if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
	                		loginUser.setBusinessTypes(new ArrayList<>());
	                		for(AgentRelationBusinessConfig busiConfig : agentbusiConfigList) {
	                			BusinessConfigItem item = new BusinessConfigItem();
		                			item.setBusinessType(busiConfig.getBusinessType());
		                			item.setEditFeeState(busiConfig.getEditFeeState());
		                			loginUser.getBusinessTypes().add(item);
	                		}
	                	}
	                    flag = true;
	                }
		        }else if(role == 4) {
		        	//介绍人
		        	AgentReferrerBusinessConfigSearch search = new AgentReferrerBusinessConfigSearch();
					search.setReferrerUserId(loginUser.getId());
					Long count = AgentReferrerBusinessConfigService.self().countReferrerUserBySearch(search);
					if(count > 0) {
						loginUser.setRoleType(ERoleType.Referrer.index());
	                    loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
	                    flag = true;
					}
		        }else if(role == 5) {
		        	//店员
		        	Clerk clerk = ClerkService.self().getByLastLogin(user.getId());
		        	if(clerk != null) {
		        		loginUser.setRoleType(ERoleType.Clerk.index());
	                    loginUser.setParentId(clerk.getMerchantUserId());
	                    loginUser.setCanCancelOrder(clerk.getCanCancelOrder());
	                    flag = true;
		        	}
		        }
		        if(flag) {break;}
        	}
	        if(!flag) {
	        	throw new LogicException("请选择正确的入口登录");
	        }
        }else {
        	//最后一次登陆
        	if(StringTools.isNotBlank(user.getLastLoginType())){
        		 String[] types = user.getLastLoginType().split(",");
        		 if(types != null && types.length > 0){
        			 Integer roleType = Integer.valueOf(types[0]);
        			 if(ERoleType.Agent.index().equals(roleType)){
        				 Agent agent = AgentService.self().getByUserId(user.getId());
                         if(agent != null){
                        	 loginUser.setRoleType(ERoleType.Agent.index());
                             loginUser.setLevel(agent.getLevel());
                             loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Open.index()); //默认开启
                             List<AgentBusinessConfig> agentbusiConfigList = AgentBusinessConfigService.self().findByUserId(agent.getUserId());
                             if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
     	                		loginUser.setBusinessTypes(new ArrayList<>());
     	                		for(AgentBusinessConfig busiConfig : agentbusiConfigList) {
     	                			BusinessConfigItem item = new BusinessConfigItem();
     	                			item.setBusinessType(busiConfig.getBusinessType());
     	                			item.setEditFeeState(2);	//默认开启
     	                			loginUser.getBusinessTypes().add(item);
     	                		}
     	                	 }
                             flag = true;
                         }
        			 }else if(ERoleType.Merchant.index().equals(roleType)){
        				 Long userId = Long.valueOf(types[1]);
        				 AgentRelation agentRelation = AgentRelationService.self().getByKeys(userId,user.getId());
                         if(agentRelation != null && ERoleType.Merchant.index().equals(agentRelation.getRoleType())){
                             loginUser.setRoleType(agentRelation.getRoleType());
                             loginUser.setParentId(agentRelation.getUserId());
                             loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
                             flag = true;
                         }
        			 }else if(ERoleType.Partner.index().equals(roleType)){
        				 Long userId = Long.valueOf(types[1]);
        				 AgentRelation agentRelation = AgentRelationService.self().getByKeys(userId,user.getId());
                         if(agentRelation != null && ERoleType.Partner.index().equals(agentRelation.getRoleType())){
                             loginUser.setRoleType(agentRelation.getRoleType());
                             loginUser.setParentId(agentRelation.getUserId());
                             loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
                        	 List<AgentRelationBusinessConfig> agentbusiConfigList = AgentRelationBusinessConfigService.self()
     	                    		.findByUserKeys(agentRelation.getUserId(),agentRelation.getRelationUserId());
     	                	 if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
     	                		loginUser.setBusinessTypes(new ArrayList<>());
     	                		for(AgentRelationBusinessConfig busiConfig : agentbusiConfigList) {
     	                			BusinessConfigItem item = new BusinessConfigItem();
     	                			item.setBusinessType(busiConfig.getBusinessType());
     	                			item.setEditFeeState(busiConfig.getEditFeeState());
     	                			loginUser.getBusinessTypes().add(item);
     	                		}
     	                	 }
                             flag = true;
                         }
        			 }else if(ERoleType.Referrer.index().equals(roleType)){
        				 AgentReferrerBusinessConfigSearch search = new AgentReferrerBusinessConfigSearch();
        				 search.setReferrerUserId(loginUser.getId());
        				 Long count = AgentReferrerBusinessConfigService.self().countReferrerUserBySearch(search);
        				if(count > 0) {
                             loginUser.setRoleType(ERoleType.Referrer.index());
                             loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
                             flag = true;
                         }
        			 }else if(ERoleType.Clerk.index().equals(roleType)){
        				 Long userId = Long.valueOf(types[1]);
                         Clerk clerk = ClerkService.self().getJoinByKeys(user.getId(), userId);
                         if(clerk != null) {
                        	 loginUser.setRoleType(ERoleType.Clerk.index());
                             loginUser.setParentId(clerk.getMerchantUserId());
                             loginUser.setCanCancelOrder(clerk.getCanCancelOrder());
                             flag = true;
                         }
        			 }
        		 }
        	}
        	
        	if(!flag) {
            	//自动登陆，优先级代理 > 介绍人 > 合伙人 > 商户 > 店员
        		Agent agent = AgentService.self().getByUserId(user.getId());
                if(agent != null){
                	loginUser.setRoleType(ERoleType.Agent.index());
                	loginUser.setLevel(agent.getLevel());
                	loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Open.index()); //默认开启
                	List<AgentBusinessConfig> agentbusiConfigList = AgentBusinessConfigService.self().findByUserId(agent.getUserId());
                    if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
                		loginUser.setBusinessTypes(new ArrayList<>());
                		for(AgentBusinessConfig busiConfig : agentbusiConfigList) {
                			BusinessConfigItem item = new BusinessConfigItem();
                			item.setBusinessType(busiConfig.getBusinessType());
                			item.setEditFeeState(2);	//默认开启
                			loginUser.getBusinessTypes().add(item);
                		}
                	}
                	flag = true;
                }else {
                	 AgentReferrerBusinessConfigSearch search = new AgentReferrerBusinessConfigSearch();
    				 search.setReferrerUserId(loginUser.getId());
    				 Long count = AgentReferrerBusinessConfigService.self().countReferrerUserBySearch(search);
    				if(count > 0) {
    					  loginUser.setRoleType(ERoleType.Referrer.index());
                          loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
                          flag = true;
    				}else {
	                	AgentRelation agentRelation = AgentRelationService.self().getLastLogin(user.getId());
	    	        	if (agentRelation != null) {
	    	        		loginUser.setRoleType(agentRelation.getRoleType());		//TODO 这里偷一个懒，如果AgentRelation有变化修改有效
	                        loginUser.setParentId(agentRelation.getUserId());
	                        loginUser.setCanCancelOrder(PowerEnum.CanCancelOrder.Close.index()); //默认关闭
	                        if(ERoleType.Partner.index().equals(agentRelation.getRoleType())) {
	                        	List<AgentRelationBusinessConfig> agentbusiConfigList = AgentRelationBusinessConfigService.self()
	     	                    		.findByUserKeys(agentRelation.getUserId(),agentRelation.getRelationUserId());
	     	                	 if(agentbusiConfigList != null && agentbusiConfigList.size() > 0) {
	     	                		loginUser.setBusinessTypes(new ArrayList<>());
	     	                		for(AgentRelationBusinessConfig busiConfig : agentbusiConfigList) {
	     	                			BusinessConfigItem item = new BusinessConfigItem();
	     	                			item.setBusinessType(busiConfig.getBusinessType());
	     	                			item.setEditFeeState(busiConfig.getEditFeeState());
	     	                			loginUser.getBusinessTypes().add(item);
	     	                		}
	     	                	 }
	                        }
	                        flag = true;
	                    }else {
	                    	Clerk clerk = ClerkService.self().getByLastLogin(user.getId());
	        	        	if(clerk != null) {
	        	        		loginUser.setRoleType(ERoleType.Clerk.index());
	                            loginUser.setParentId(clerk.getMerchantUserId());
	                            loginUser.setCanCancelOrder(clerk.getCanCancelOrder());
	                            flag = true;
	        	        	}
	                    }
    				}
                }
            }
        }
        
        if(flag) {
        	return loginUser;
        }
        return null;
    }
}
